package kite.sso.client;

import com.alibaba.fastjson.JSONObject;
import com.tfrunning.core.message.Session;
import com.tfrunning.toolkit.ConsKit;
import com.tfrunning.toolkit.Prop;
import com.tfrunning.toolkit.PropKit;
import kite.sso.util.HttpResponseUtil;
import org.apache.http.Consts;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 功能描述: <br>
 * 所属包名: kite.sso.client<br>
 * 创建人　: 白剑<br>
 * 创建时间: 06/11/2018 15:57 Monday<br>
 * 当前版本: 1.0<br>
 * 修改历史: <br>
 * 修改时间　　　　　修改人　　　　　版本变更　　　　　修改说明<br>
 * -----------------------------------------------------<br>
 * <br>
 */
public abstract class SsoLoginClient extends HttpServlet {

    private Prop prop;

    public SsoLoginClient() {
        super();
        prop = PropKit.use(ConsKit.CONF_PROPERTIES);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req, resp);
    }

    @SuppressWarnings("TryFinallyCanBeTryWithResources")
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        String code = req.getParameter("code");

        if (null == code) {
            String authorizeUrl = prop.get("client.userAuthorizationUri") +
                    "?client_id=kite&redirect_uri=" + prop.get("local.redirectUri") + "&response_type=code";
            resp.sendRedirect(authorizeUrl);
        } else {

            CloseableHttpClient httpClient = HttpClients.createDefault();
            CloseableHttpResponse tokenResponse = null;
            CloseableHttpResponse userResponse = null;

            try {

                HttpPost httpTokenPost = new HttpPost(prop.get("client.accessTokenUri"));

                List<NameValuePair> params = new ArrayList<>();
                params.add(new BasicNameValuePair("grant_type", "authorization_code"));
                params.add(new BasicNameValuePair("code", code));
                params.add(new BasicNameValuePair("client_id", prop.get("client.clientId")));
                params.add(new BasicNameValuePair("client_secret", prop.get("client.clientSecret")));
                params.add(new BasicNameValuePair("redirect_uri", prop.get("local.redirectUri")));
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, Consts.UTF_8);
                httpTokenPost.setEntity(entity);
                tokenResponse = httpClient.execute(httpTokenPost);
                if (tokenResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                    throw new RuntimeException("获取认证Token失败，StatusLine: " + tokenResponse.getStatusLine());
                }
                JSONObject authInfo = HttpResponseUtil.getResponseData(tokenResponse.getEntity().getContent());
                String accessToken = authInfo.get("access_token").toString();

                // 获取个人信息
                HttpGet httpUserGet = new HttpGet(prop.get("resource.userInfoUri")
                        + "?access_token=" + accessToken);
                userResponse = httpClient.execute(httpUserGet);
                if (userResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                    throw new RuntimeException("获取用户信息失败，StatusLine: " + tokenResponse.getStatusLine());
                }
                JSONObject userInfo = HttpResponseUtil.getResponseData(userResponse.getEntity().getContent());

                // 设置session
                Session session = JSONObject.parseObject(userInfo.toJSONString(), Session.class);
                session.setTocken(accessToken);
                HttpSession httpSession = req.getSession();
                httpSession.setAttribute(ConsKit.USER_SESSION, session);

                // TODO 测试用
                System.out.println("------------- session build from sso: -------------");
                System.out.println(JSONObject.toJSON(session));
                System.out.println("---------------------------------------------------");
                customSession(session);

                // 跳转到个性化登录
                // 这时候基本的userId和userName已经设置到session，各个系统个性化的时候可以利用过滤器，根据userId完善session信息
                resp.sendRedirect(prop.get("local.indexUri"));

            } finally {
                httpClient.close();
                if (null != tokenResponse) {
                    tokenResponse.close();
                }
                if (null != userResponse) {
                    userResponse.close();
                }
            }
        }
    }

    /**
     * 功能描述: 自定义session<br>
     * 创建人　: 白剑<br>
     * 创建时间: 2018/06/29 13:34:52<br>
     */
    protected abstract void customSession(Session session);

}
